<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>TouchTest</title>
    <style>

      .touchpad {
        height: calc(100% - 40px);
        background-color: #71baf6;
        white-space: pre-wrap;
        /* 两行, 第二行3列 */
        display: grid;
        grid-template-rows: 50px auto;
        grid-template-columns: repeat(3, 1fr);
      }

      .touchPoint {
        width: 50px;
        height: 50px;
        border-radius: 5vw;
        display: flex;
        align-items: center;
        justify-content: center;
        position: fixed;
        /**/
        top: 0;
        left: 0;
      }
    </style>
</head>
<body style="margin: 0; padding: 0;overflow: hidden">

<div id="app" style="height:100vh; padding: 20px; background-color: #0a0;">
    <div id="touchpad" class="touchpad">
        <!--第1行-->
        <div v-text="topText" style="grid-column: 1/4"></div>
        <!--第2行-->
        <div v-text="startText"></div>
        <div v-text="endText"></div>
        <div v-text="moveText"></div>
    </div>
</div>

<script type="module">
  import "../common/plugins/vue/2.6.11.min.js"

  new Vue({
    el: '#app',
    data() {
      return {
        version: 'v2',
        topText: 'topText',
        startText: 'startText',
        endText: 'endText',
        moveText: 'moveText',
        //触摸点
        points: new Array(10),
        lastX: new Array(10),
        lastY: new Array(10),
        downX: new Array(10),
        downY: new Array(10),
      }
    },
    watch: {},
    mounted() {
      console.log('mounted')

      let touchpad = document.getElementById('touchpad')
      touchpad.addEventListener('touchstart', e0 => {
        e0.preventDefault()
        let events = this.castList(e0.changedTouches)
        this.startText = JSON.stringify(events, null, 2)

        events.forEach(e => {
          let id = e.identifier
          this.lastX[id] = e.pageX
          this.lastY[id] = e.pageY
          this.downX[id] = this.lastX[id]
          this.downY[id] = this.lastY[id]

          //创建dom
          let point = document.createElement('div')
          point.innerText = id + ''
          point.className = `touchPoint`
          point.style.zIndex = (2000 + id) + ''
          point.style.backgroundColor = `hsl(${id * 360 / 10}, 100%, 50%)`
          point.style.left = `${e.pageX - 25}px`
          point.style.top = `${e.pageY - 25}px`
          document.body.appendChild(point)
          this.points[id] = point
        })

        // this.topText = `touchstart.targetTouches=${e0.targetTouches.length}`
        this.topText = `touchstart.PointCount=${this.getPointCount()}`
      })

      touchpad.addEventListener('touchend', e0 => {
        e0.preventDefault()
        let events = this.castList(e0.changedTouches)
        this.endText = JSON.stringify(events, null, 2)
        // this.topText = `touchend.targetTouches=${e0.targetTouches.length}`//恒是0

        events.forEach(e => {
          let id = e.identifier
          this.lastX[id] = null
          this.lastY[id] = null
          this.downX[id] = null
          this.downY[id] = null
          this.points[id].remove()
          this.points[id] = null
        })

        this.topText = `touchend.PointCount=${this.getPointCount()}`
      })

      touchpad.addEventListener('touchmove', e0 => {
        e0.preventDefault()
        let events0 = this.castList(e0.changedTouches)
        //过滤没有移动的事件
        let events = []
        events0.forEach(e => {
          let id = e.identifier
          if (this.lastX[id] === e.pageX && this.lastY[id] === e.pageY) return
          events.push(e)
        })
        if (!events.length) return
        this.moveText = JSON.stringify(events, null, 2)
        // this.topText = `touchmove.targetTouches=${e0.targetTouches.length}`//targetTouches.length 经常会偏小...
        this.topText = `touchmove.PointCount=${this.getPointCount()}`

        events.forEach(e => {
          let id = e.identifier

          let point = this.points[id]
          point.style.left = `${e.pageX - 25}px`
          point.style.top = `${e.pageY - 25}px`

          this.lastX[id] = e.pageX
          this.lastY[id] = e.pageY
        })
      })

      touchpad.addEventListener('touchcancel', e0 => {
        this.endText = 'touchcancel'
        for (let i = 0; i < this.points.length; i++) {
          if (this.points[i]) {
            this.points[i].remove()
            this.points[i] = null
          }
        }
        this.topText = `touchcancel.PointCount=${this.getPointCount()}`
      });
    },
    methods: {
      /**
       * cast 触摸事件
       * @param list 触摸事件list; e.targetTouches, e.changedTouches
       */
      castList(list) {
        const keys = [
          'identifier',//触摸点id
          'pageX',//相对于整个页面（包括滚动条）的 X 和 Y 坐标。
          'pageY',
          'clientX',//相对于浏览器窗口的 X 和 Y 坐标; 一般没用!!
          'clientY',
          /*
          如果设备支持压力感应，那么这两个值会给出触摸点的压力半径
          实际设备中: move事件会很容易一直触发,因为这个值一直在变...
           */
          'radiusX',
          'radiusY',
          'rotationAngle',//如果设备支持角度旋转，则该属性给出触摸点的角度
          'screenX',//相对于整个屏幕（包括任务栏和其他UI元素）的 X 和 Y 坐标。
          'screenY',
        ]
        let res = []
        for (let i = 0; i < list.length; i++) {
          let item = {}
          for (let key of keys) {
            item[key] = list[i][key]
          }
          res.push(item)
        }
        return res
      },
      getPointCount() {
        let res = 0
        for (let i = 0; i < this.points.length; i++) {
          if (this.points[i]) res++
        }
        return res
      }
    },
  })
</script>
</body>
</html>